package com.example.doctor.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.config.impl.WxMaDefaultConfigImpl;
import cn.hutool.core.util.RandomUtil;
import com.example.common.entity.DoctorBaseInfo;
import com.example.common.entity.HospitalDepartment;
import com.example.common.redis.RedisService;
import com.example.common.support.ApiException;
import com.example.common.support.Result;
import com.example.common.utils.HxUtils;
import com.example.common.utils.MapUtils;
import com.example.common.utils.SmsUtils;
import com.example.doctor.dto.req.GetPhoneCode;
import com.example.doctor.dto.req.GetUserTel;
import com.example.doctor.dto.req.GetWxInfoR;
import com.example.doctor.dto.req.SmsLogin;
import com.example.doctor.jpa.DoctorBaseInfoRepository;
import com.example.doctor.jpa.HospitalDepartmentRepository;
import com.example.doctor.jpa.MsgConfigRepository;
import com.example.doctor.service.UserLoginService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import me.chanjar.weixin.mp.config.impl.WxMpDefaultConfigImpl;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;

import java.net.InetAddress;
import java.util.*;

/**
 * @author sifan
 * @PackagName:com.example.doctor.service.impl
 * @ClassName: UserLoginServiceImpl
 * @Description:
 * @date:2021/1/18 15:36
 */
@Service
@Slf4j
public class UserLoginServiceImpl implements UserLoginService {

    //模板id获取验证码
    final static String templateId = "846823";

    @Resource
    RedisService redisService;

    @Resource
    DoctorBaseInfoRepository doctorBaseInfoRepository;

    @Resource
    HospitalDepartmentRepository hospitalDepartmentRepository;

    @Resource
    HxUtils hxUtils;

    @Resource
    private MsgConfigRepository msgConfigRepository;

    @Value("${appID}")
    private String appID;

    @Value("${appsecret}")
    private String appsecret;


    @Override
    public boolean getPhoneCode(GetPhoneCode getPhoneCode) {

        DoctorBaseInfo doctorBaseInfo = doctorBaseInfoRepository.findByPhone(getPhoneCode.getTel());
        if (ObjectUtils.isEmpty(doctorBaseInfo)) {
            throw new ApiException(400, "该手机号未注册，请联系信息科");
        }
        if (doctorBaseInfo.getDisable()) {
            throw new ApiException(400, "用户已禁用");
        }
        String phoneCode = RandomUtil.randomNumbers(6);
        
        SmsUtils.sendSmsMessage(getPhoneCode.getTel(), Collections.singletonList(phoneCode), templateId);

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 5);

        doctorBaseInfo.setCodeTime(calendar.getTime());
        doctorBaseInfo.setCode(phoneCode);
        try {
            doctorBaseInfoRepository.save(doctorBaseInfo);
            return true;
        } catch (Exception e) {
            //TODO: handle exception
        }
        return false;
        
    }

    @Override
    public HashMap<String, Object> smsLogin(SmsLogin smsLogin) {
        // String phoneCodd = redisService.getString(smsLogin.getTel());
        
        DoctorBaseInfo doctorBaseInfo = doctorBaseInfoRepository.findByPhone(smsLogin.getTel());
        if (ObjectUtils.isEmpty(doctorBaseInfo)) {
            throw new ApiException(400, "该手机号未注册，请联系信息科");
        }
        if (new Date().after(doctorBaseInfo.getCodeTime())) {
            throw new ApiException(400, "验证码失效");
        }
        if (!doctorBaseInfo.getCode().equals(smsLogin.getSmscode())) {
            throw new ApiException(400, "验证码错误");
        }
        if (doctorBaseInfo.getDisable()) {
            throw new ApiException(400, "用户已禁用");
        }
        
        HashMap<String, Object> hashMap = new HashMap<>();

        boolean needsave = false;
        try {
            if(smsLogin.getCode() != null && !smsLogin.getCode().isEmpty() && smsLogin.getCode().length() >= 0){
                WxMpUser wxMpUser = null;
                WxOAuth2AccessToken accessToken = null;
                try {   
                    WxMpService wxMpService = new WxMpServiceImpl();
                    WxMpDefaultConfigImpl configStorage = new WxMpDefaultConfigImpl();
                    configStorage.setAppId(appID);//TODO
                    configStorage.setSecret(appsecret);//TODO
                    wxMpService.setWxMpConfigStorage(configStorage);
        
                    accessToken = wxMpService.getOAuth2Service().getAccessToken(smsLogin.getCode());
                    wxMpUser = wxMpService.getUserService()
                            .userInfo(accessToken.getOpenId(), "zh_CN");
                
                } catch (Exception e) {
                    hashMap.put("sess", false);
                    return hashMap;
                }

                if(accessToken== null || accessToken.getOpenId().isEmpty()){
                    hashMap.put("sess", false);
                    return hashMap;
                }
                if(doctorBaseInfo.getOpenId() == null || doctorBaseInfo.getOpenId().length() == 0){
                    //保存用户信息
                    doctorBaseInfo.setOpenId(accessToken.getOpenId());
                    doctorBaseInfo.setHxId(accessToken.getOpenId() + appID);
                    String hxPwd = hxUtils.enCodePwd(accessToken.getOpenId() + appID);
                    hxUtils.createHXID(doctorBaseInfo.getHxId(),hxPwd);
                    doctorBaseInfo.setHxPwd(hxPwd);
                    doctorBaseInfoRepository.save(doctorBaseInfo);
                }
                
                if(doctorBaseInfo.getOpenId() == null || doctorBaseInfo.getOpenId().length() == 0){
                    hashMap.put("sess", false);
                    hashMap.put("msg", "获取微信信息失败，请重试");
                    return hashMap;
                }
            }

            if(doctorBaseInfo.getOpenId() == null || doctorBaseInfo.getOpenId().length() == 0){
                hashMap.put("sess", false);
                hashMap.put("msg", "请在手机端认证");
                return hashMap;
            }

            //查询科室
            HospitalDepartment hospitalDepartment = hospitalDepartmentRepository.findById(doctorBaseInfo.getDepartId()).orElse(null);
            //封装返回参数
            hashMap.put("sess", true);
            hashMap.put("UID", doctorBaseInfo.getDcId());
            hashMap.put("Name", doctorBaseInfo.getName());
            hashMap.put("Head", doctorBaseInfo.getHead());
            hashMap.put("Title", doctorBaseInfo.getTitle());
            hashMap.put("DName", hospitalDepartment.getName());
            hashMap.put("HXID", doctorBaseInfo.getHxId());
            hashMap.put("HXPwd", doctorBaseInfo.getHxPwd());
            return hashMap;
        } catch (Exception e) {
            log.error(e.getMessage());
        }
        return null;
    }

    //#region 小程序登录

    @Value("${mappID}")
    private String mappID;

    @Value("${mappsecret}")
    private String mappsecret;

    @Override
    public HashMap<String, Object> getWxInfoR(GetWxInfoR getWxInfoR) {

        //获取openid
        WxMaService wxService = new WxMaServiceImpl();
        WxMaDefaultConfigImpl wxMaDefaultConfig = new WxMaDefaultConfigImpl();
        wxMaDefaultConfig.setAppid(mappID);//TODO
        wxMaDefaultConfig.setSecret(mappsecret);////TODO
        wxService.setWxMaConfig(wxMaDefaultConfig);

        List<String> tids = msgConfigRepository.findByType();

        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(getWxInfoR.getCode());
            if(session == null || session.getOpenid() == null || session.getOpenid().isEmpty()){
                throw new ApiException(400, "获取微信信息失败");
            }
            DoctorBaseInfo doctorBaseInfo = doctorBaseInfoRepository.findByOpenId(session.getOpenid());


            if (ObjectUtils.isEmpty(doctorBaseInfo)) {
                HashMap<String, Object> hashMap = new HashMap<>();
                hashMap.put("LoginSess", false);
                hashMap.put("OpenID", session.getOpenid());
                hashMap.put("tmplIds", tids);
                return hashMap;
            }

            if (doctorBaseInfo.getDisable()) {
                throw new ApiException(400, "用户已禁用");
            }

            if (ObjectUtils.isEmpty(doctorBaseInfo.getHxId())) {
                String hxId = session.getOpenid()+mappID;
                String hxPwd = hxUtils.enCodePwd(hxId);
                try {
                    hxUtils.createHXID(hxId, hxPwd);
                    doctorBaseInfo.setHxId(hxId);
                    doctorBaseInfo.setHxPwd(hxPwd);
                    doctorBaseInfoRepository.save(doctorBaseInfo);
                } catch (ApiException e) {
                    
                }
            }

            //查询科室
            HospitalDepartment hospitalDepartment = hospitalDepartmentRepository.findById(doctorBaseInfo.getDepartId()).orElse(null);
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("UID", doctorBaseInfo.getDcId());
            hashMap.put("Name", doctorBaseInfo.getName());
            hashMap.put("Head", doctorBaseInfo.getHead());
            hashMap.put("Title", doctorBaseInfo.getTitle());
            hashMap.put("DName", hospitalDepartment.getName());
            hashMap.put("HXID", doctorBaseInfo.getHxId());
            hashMap.put("HXPwd", doctorBaseInfo.getHxPwd());
            hashMap.put("openId", doctorBaseInfo.getOpenId());
            hashMap.put("phone", doctorBaseInfo.getPhone());
            hashMap.put("tmplIds", tids);
            hashMap.put("LoginSess", true);
            return hashMap;
        } catch (WxErrorException e) {
            throw new ApiException(400, "获取微信信息失败");
        }
    }

    @Override
    public HashMap<String, Object> GetUserTel(GetUserTel getUserTel) {

        WxMaService wxService = new WxMaServiceImpl();
        WxMaDefaultConfigImpl wxMaDefaultConfig = new WxMaDefaultConfigImpl();
        wxMaDefaultConfig.setAppid(mappID);
        wxMaDefaultConfig.setSecret(mappsecret);
        wxService.setWxMaConfig(wxMaDefaultConfig);
        WxMaJscode2SessionResult session = null;
        try {
            session = wxService.getUserService().getSessionInfo(getUserTel.getCode());
        } catch (WxErrorException e) {
            e.printStackTrace();
        }
        WxMaPhoneNumberInfo phoneNoInfo = null;
        try {
            phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), getUserTel.getEncryptedData(), getUserTel.getIv());            
        } catch (Exception e) {
            throw new ApiException(400,"获取手机信息失败，请重试");
        }
        if(phoneNoInfo == null){
            throw new ApiException(400,"获取手机信息失败，请重试");
        }
        
        DoctorBaseInfo doctorBaseInfo = doctorBaseInfoRepository.findByPhone(phoneNoInfo.getPurePhoneNumber());

        HashMap<String, Object> hashMap = new HashMap<>();
        if (ObjectUtils.isEmpty(doctorBaseInfo)) {
            throw new ApiException(400,"该手机号未注册，请联系信息科");
        }

        if (doctorBaseInfo.getDisable()) {
            throw new ApiException(400,"用户已禁用");
        }

        if (ObjectUtils.isEmpty(doctorBaseInfo.getOpenId()) || !doctorBaseInfo.getOpenId().equals(session.getOpenid())) {
            doctorBaseInfo.setOpenId(session.getOpenid());
            String hxID = doctorBaseInfo.getHxId();
            String hxPwd = doctorBaseInfo.getHxPwd();
            try {
                hxID = session.getOpenid()+mappID;
                hxPwd = hxUtils.enCodePwd(hxID);
                hxUtils.createHXID(hxID, hxPwd);
            } catch (Exception e) {
                hxID = doctorBaseInfo.getHxId();
                hxPwd = doctorBaseInfo.getHxPwd();
            }
            doctorBaseInfo.setHxId(hxID);
            doctorBaseInfo.setHxPwd(hxPwd);
            doctorBaseInfoRepository.save(doctorBaseInfo);
        }
        //查询科室
        HospitalDepartment hospitalDepartment = hospitalDepartmentRepository.findById(doctorBaseInfo.getDepartId()).orElse(null);
        hashMap.put("UID", doctorBaseInfo.getDcId());
        hashMap.put("Name", doctorBaseInfo.getName());
        hashMap.put("Head", doctorBaseInfo.getHead());
        hashMap.put("Title", doctorBaseInfo.getTitle());
        hashMap.put("DName", hospitalDepartment.getName());
        hashMap.put("HXID", doctorBaseInfo.getHxId());
        hashMap.put("HXPwd", doctorBaseInfo.getHxPwd());
        hashMap.put("openId", doctorBaseInfo.getOpenId());
        hashMap.put("LoginSess", true);
        return hashMap;

    }

        //#endregion
}
